package com.lanou3g;

public class TestMain {

	public static void main(String[] args) {
		// 需求： 要求盘子只能装一种水果
		// 装苹果
//		Plate plate = new Plate();
//		Apple apple = new Apple();
//		plate.set(apple);
//		
//		plate.set(new Banana());
//		
//		
//		Object object = plate.get();
////		if(object instanceof Apple) {
//			Apple a = (Apple) object;
////		}
		
		
		// 泛型的使用场景：限制类型，避免无谓的类型转化
//		// 只装苹果的盘子
//		Plate<Apple> applePlate = new Plate<Apple>();
//		applePlate.set(new Apple());
//		
//		// 只装香蕉的盘子
//		Plate<Banana> bananaPlate = new Plate<>();
//		bananaPlate.set(new Banana());
//		
//		Banana banana = bananaPlate.get();
		
		
		// 泛型类和泛型方法混合使用
		Banana bana = new Banana();
		Plate<Banana> plate2 = new Plate<Banana>(bana);
		plate2.set(bana);
		System.out.println(plate2.get());
		
		
		
		// 泛型： 阶段一： 声明（虚拟的类型），  阶段二： 使用（实际类型）
		//Plate<Integer> p = new Plate<Integer>();
		Plate<Apple> p = new Plate<>();
		p.set(new Apple());
		//p.set(new Banana());
		
		
		// 有界类型泛型
//		Plate2<Apple> p2 = new Plate2<>();
		
		
		// 泛型不支持继承
		Food food = new Apple();
		Plate<Food> pf = null;
		Plate<Apple> pa = new Plate<>(new Apple());
		//pf = pa;
		
		//pf.set(new Banana());
		
//		pf.set(pa.get());
		
		// Plate<Food> 不是 Plate<Apple> 的父类
		// ---------------泛型通配符-----------------------
		// 为了解决此问题 -> 泛型通配符
		Plate<?> pw = null;
		pw = pa;
		System.out.println(pw);
		Object item = pw.get(); // 使用无限定通配符后，获取的元素都会变成Object类型
		System.out.println(item);
		
		//pw.set(new Food()); // 使用无限定通配符后，丧失了写入的能力
		// ---------------泛型通配符结束-----------------------
		
		
		// 上限通配符
		Plate<? extends Fruit> plate = new Plate<Apple>();
		Fruit fruit = plate.get();  // 上限通配符，获取的元素是T类型
		// plate.set();  // Fruit、Apple、Banana  // 使用无限定通配符后，同样丧失了写入的能力（因为不能确定泛型到底是哪一种类型）
		
		
		
		// 下限通配符
		Plate<? super Fruit> plate21 = new Plate<Object>();
		Object item1 = plate21.get(); // 下限通配符，获取的元素类型只能是Object类型
		plate21.set(new Apple());
		plate21.set(new Fruit());
		
		
		Plate<? super Fruit> pp = new Plate<Fruit>();
		//pp.set(new Object());
		
	}

}
